/**
 * Copyright 2007-2010 非也
 * All rights reserved. 
 * 
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License v3 as published by the Free Software
 * Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
 *
 */
package org.fireflow2.designer.eclipse.properties.activity;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.DialogCellEditor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.fireflow.engine.modules.script.ScriptContextVariableNames;
import org.fireflow.model.binding.Assignment;
import org.fireflow.model.binding.ServiceBinding;
import org.fireflow.model.binding.impl.AssignmentImpl;
import org.fireflow.model.data.Expression;
import org.fireflow.model.data.Input;
import org.fireflow.model.data.Output;
import org.fireflow.model.data.impl.ExpressionImpl;
import org.fireflow.model.servicedef.InterfaceDef;
import org.fireflow.model.servicedef.OperationDef;
import org.fireflow.model.servicedef.ServiceDef;
import org.fireflow.pdl.fpdl20.process.WorkflowProcess;
import org.fireflow.service.human.HumanService;
import org.fireflow2.designer.eclipse.modelwrapper.ModelWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.SubProcessWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.ActivityWrapper;
import org.fireflow2.designer.eclipse.properties.IPropertyValidateListener;
import org.fireflow2.designer.eclipse.properties.common.XPathExpressionEditDialog;
import org.firesoa.common.util.ScriptLanguages;

/**
 * 
 * @author 非也 nychen2000@163.com Fire Workflow 官方网站：www.firesoa.com 或者
 *         www.fireflow.org
 * 
 */
public class ServiceBindingEditPanel {
	private FormToolkit formToolkit = null;
	private boolean canSelectServiceAndMethod = true;
	
	private ServiceDef service = null;
	private ServiceBinding serviceBinding = null;
	private SubProcessWrapper subProcessWrapper = null;
	private ActivityWrapper activityWrapper = null;

	// widget
	Text serviceNameText = null;// 服务名称
	Text methodNameText = null;// 操作名称
	TableViewer parameterAssignmentTableViewer = null;
	Text returnBindingExpression = null;
	Button editReturnBindingExpressionButton  = null;

	private List<IPropertyValidateListener> listeners = new ArrayList<IPropertyValidateListener>();
	
	public void addServicePropertyModifyListener(IPropertyValidateListener listener){
		listeners.add(listener);
	}
	
	public List<IPropertyValidateListener> getServicePropertyModifyListeners(){
		return listeners;
	}

	/**
	 * 
	 * @param subProcessWrapper
	 * @param b
	 *            表示service和method的选择按钮是否有效。
	 */
	public ServiceBindingEditPanel(	boolean b) {
		canSelectServiceAndMethod = b;
	}
	
	public void setActivityWrapper(ActivityWrapper actWrapper){
		this.activityWrapper = actWrapper;
	}

	public void setSubProcessWrapper(SubProcessWrapper subProcessWrapper){
		this.subProcessWrapper = subProcessWrapper;
	}
	public void setInput(ServiceBinding svcBd) {
		serviceBinding = svcBd;
	}
	
	public void setFormToolkit(FormToolkit toolkit){
		this.formToolkit = toolkit;
	}
	
	public void setServiceDef(ServiceDef svc){
		this.service = svc;
	}
	
	protected void updateServiceReference(ServiceDef serviceTmp){
		if (serviceBinding!=null && serviceTmp.getId().equals(serviceBinding.getServiceId())){
			return ;//service没有变化则返回
		}
		this.service = serviceTmp;
		List<OperationDef> operations = serviceTmp.getInterface().getOperations();
		if (operations==null || operations.size()==0){
			return ;//没有opertaion也返回
		}
		
		//1、首先清楚ServiceBinding的绑定信息
		serviceBinding.setServiceId(null);
		serviceBinding.setOperationName(null);
		serviceBinding.setInputAssignments(new ArrayList<Assignment>());
		serviceBinding.setOutputAssignments(new ArrayList<Assignment>());
		
		//2、绑定 service		
		serviceBinding.setServiceId(serviceTmp.getId());
		
		//3、默认绑定第一个方法
		OperationDef operation = operations.get(0);
		updateOperationReference(operation);
		
	}
	
	protected void updateOperationReference(OperationDef operation){
		if (operation==null){
			return ;
		}
		if (serviceBinding!=null && operation.getOperationName().equals(serviceBinding.getOperationName())){
			return;
		}
		serviceBinding.setOperationName(operation.getOperationName());
		
		if(operation!=null){
			//初始化servicebinding中的input assignment 和output assignment
			serviceBinding.getInputAssignments().clear();
			serviceBinding.getOutputAssignments().clear();
			
			List<Input> inputList = operation.getInputs();	

			for (Input input : inputList) {
				String pName = input.getName();
				Assignment inputAssignment = new AssignmentImpl();

				ExpressionImpl fromExp = new ExpressionImpl();
				fromExp.setLanguage(ScriptLanguages.XPATH.name());
				fromExp.setName("EmptyExpression");
				fromExp.setDisplayName(Expression.EXPRESSION_DISPLAY_NAME_TIP);
				inputAssignment.setFrom(fromExp);

				ExpressionImpl toExp = new ExpressionImpl();
				toExp.setLanguage(ScriptLanguages.XPATH.name());
				toExp.setName(pName);
				toExp.setDisplayName(pName);
				toExp.setBody(ScriptContextVariableNames.INPUTS + "/" + pName);
				toExp.setDataType(input.getDataType());
				inputAssignment.setTo(toExp);

				serviceBinding.getInputAssignments().add(inputAssignment);
			}

			List<Output> outputList = operation.getOutputs();
			// 返回值
			if (outputList!=null && outputList.size()>0) {
				Output output = outputList.get(0);
				
				Assignment outputAssignment = new AssignmentImpl();
				ExpressionImpl fromExp = new ExpressionImpl();
				fromExp.setLanguage(ScriptLanguages.XPATH.name());
				String outputName = output.getName();
				fromExp.setName(outputName);
				String displayName = output.getDisplayName();
				if (displayName==null || displayName.trim().equals("")){
					displayName = outputName;
				}
				fromExp.setDisplayName(displayName);
				fromExp.setBody(ScriptContextVariableNames.OUTPUTS + "/"
						+ outputName);
				
				fromExp.setDataType(output.getDataType());

				ExpressionImpl toExp = new ExpressionImpl();
				toExp.setLanguage(ScriptLanguages.XPATH.name());
				toExp.setName("EmptyExpression");
				toExp.setDisplayName("请编辑该表达式...");
				outputAssignment.setTo(toExp);

				serviceBinding.getOutputAssignments().add(outputAssignment);
			} else {

			}
		}
		activityWrapper.fireStructureChange("SERVICE_BINDING", serviceBinding);
		refresh();
	}
	public void removeInputAssignmentExpression(Assignment assignment){
		serviceBinding.getInputAssignments().remove(assignment);
		activityWrapper.fireStructureChange("SERVICE_BINDING", serviceBinding);
		refresh();
	}
	public void createInputAssingmentExpression(Input input){
		String pName = input.getName();
		Assignment inputAssignment = new AssignmentImpl();

		ExpressionImpl fromExp = new ExpressionImpl();
		fromExp.setLanguage(ScriptLanguages.XPATH.name());
		fromExp.setName("EmptyExpression");
		fromExp.setDisplayName(Expression.EXPRESSION_DISPLAY_NAME_TIP);
		inputAssignment.setFrom(fromExp);

		ExpressionImpl toExp = new ExpressionImpl();
		toExp.setLanguage(ScriptLanguages.XPATH.name());
		toExp.setName(pName);
		toExp.setDisplayName(pName);
		toExp.setBody(ScriptContextVariableNames.INPUTS + "/" + pName);
		toExp.setDataType(input.getDataType());
		inputAssignment.setTo(toExp);

		serviceBinding.getInputAssignments().add(inputAssignment);
		
		activityWrapper.fireStructureChange("SERVICE_BINDING", serviceBinding);
		refresh();
	}

	public Control createControl(final Composite parent) {
		final Composite composite = getWidgetFactory()
				.createComposite(parent);
		

		
		GridLayout gridLayout = new GridLayout(3, false);
		composite.setLayout(gridLayout);

		//服务名
		Label lb = getWidgetFactory().createLabel(composite, "服务名称：");

		serviceNameText = getWidgetFactory().createText(composite, "");
		serviceNameText.setEditable(false);
		if (this.canSelectServiceAndMethod){
			serviceNameText.setBackground(ColorConstants.white);
		}else{
			serviceNameText.setBackground(ColorConstants.button);
		}		
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		if (!canSelectServiceAndMethod){
			gridData.horizontalSpan = 2;
		}else{
			gridData.horizontalSpan = 1;
		}
		serviceNameText.setLayoutData(gridData);

		if (canSelectServiceAndMethod) {//选择Service
			Button bt = new Button(composite, SWT.PUSH);
			bt.setText("...");
			bt.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					ModelWrapper wrapper = (ModelWrapper)subProcessWrapper.getParent();
					WorkflowProcess process = (WorkflowProcess)wrapper.getWorkflowModelElement();
					ServiceSelectionDialog dialog = new ServiceSelectionDialog(parent.getShell(),process);
					
					int result = dialog.open();
					if (result==Dialog.OK){
						ServiceDef serviceTemp = dialog.getSelectedService();
						updateServiceReference(serviceTemp);

					}
					
				}
			});
		}
		//操作名
		lb = getWidgetFactory().createLabel(composite, "操作名称：");
		methodNameText = getWidgetFactory().createText(composite, "");
		methodNameText.setEditable(false);
		if (canSelectServiceAndMethod){
			methodNameText.setBackground(ColorConstants.white);
		}else{
			methodNameText.setBackground(ColorConstants.button);
		}
		
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		if (!canSelectServiceAndMethod){
			gridData.horizontalSpan = 2;
		}else{
			gridData.horizontalSpan = 1;
		}
		methodNameText.setLayoutData(gridData);
		if (canSelectServiceAndMethod) {
			Button bt = new Button(composite, SWT.PUSH);
			bt.setText("...");
			bt.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					OperationSelectionDialog dialog = new OperationSelectionDialog(parent.getShell(),service);
					int result = dialog.open();
					if (result == Dialog.OK){
						OperationDef operation = dialog.getSelectedOperation();
						updateOperationReference(operation);
					}
				}
			});
		}

		
		//输入参数映射
		Label label = getWidgetFactory().createLabel(composite,"输入参数绑定：");
		parameterAssignmentTableViewer = new TableViewer(composite, SWT.MULTI | SWT.BORDER
				| SWT.V_SCROLL| SWT.FULL_SELECTION);
		Table table = parameterAssignmentTableViewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		
		final String[] columnNames = new String[] { "参数名称","类型" ,"赋值表达式" };
		int[] columnAlignments = new int[] { SWT.LEFT,SWT.LEFT, SWT.LEFT};
		for (int i = 0; i < columnNames.length; i++) {
			TableColumn tableColumn = new TableColumn(table,
					columnAlignments[i]);
			tableColumn.setText(columnNames[i]);
			tableColumn.setResizable(true);
			tableColumn.setMoveable(true);
		}
		
		parameterAssignmentTableViewer.setContentProvider(new MyTableContentProvider());
		parameterAssignmentTableViewer.setLabelProvider(new MyTableLabelProvider());
		parameterAssignmentTableViewer.setColumnProperties(columnNames);
		parameterAssignmentTableViewer.setCellModifier(new ICellModifier(){

			public boolean canModify(Object element, String property) {
				if (property.equals(columnNames[2])){
					return true;
				}
				return false;
			}

			public Object getValue(Object element, String property) {
				if (property.equals(columnNames[2])){
					Assignment assignment = (Assignment) element;
					Expression fromExp = assignment.getFrom();
					return fromExp;
				}
				return null;
			}

			public void modify(Object element, String property, Object value) {
				if (property.equals(columnNames[2])){
					TableItem tableItem = (TableItem)element;
					Assignment assignment = (Assignment)tableItem.getData();
					Expression oldFromExp = assignment.getFrom();
					Expression newFromExp = (Expression)value;
					assignment.setFrom(newFromExp);
					
					//发布事件，更新脏标志
					if (activityWrapper!=null){
						activityWrapper.firePropertyChange("toexpression_of_output_assignment", oldFromExp, newFromExp);
					}
					//刷新
					refresh();
				}
			}
			
		});
		
		CellEditor[] cellEditors = new CellEditor[]{null,null,new MyCellEditor(parameterAssignmentTableViewer.getTable())};
		parameterAssignmentTableViewer.setCellEditors(cellEditors);
		
		gridData = new GridData(GridData.FILL_HORIZONTAL|GridData.FILL_VERTICAL);
		gridData.grabExcessVerticalSpace=true;
		gridData.heightHint = 60;
		if (!this.canSelectServiceAndMethod){
			gridData.horizontalSpan = 2;
		}else{
			gridData.horizontalSpan = 1;
		}		
		table.setLayoutData(gridData);
		
		//按钮
		if (canSelectServiceAndMethod) {
			Composite parameterButtonPanel = formToolkit.createComposite(composite);
			parameterButtonPanel.setLayout(new GridLayout(1,true));
			Button addParamAssignButton = formToolkit.createButton(parameterButtonPanel,"+", SWT.PUSH);
			addParamAssignButton.setToolTipText("新增输入参数绑定");
			addParamAssignButton.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					if (service != null) {
						if (service.getInterface() != null){
							String operationName = serviceBinding.getOperationName();
							OperationDef operation = service.getInterface()
									.getOperation(operationName);
							if (operation == null) {
								MessageDialog.openError(composite.getShell(), "错误",
										"服务接口【" + service.getInterface().getName()
												+ "】中没有名为【" + operationName + "】的方法。");
							} else {
								InputSelectionDialog dialog = new InputSelectionDialog(
										composite.getShell(), operation.getInputs());
								int result = dialog.open();
								if (result == Dialog.OK){
									Input input = dialog.getSelectedInput();
									createInputAssingmentExpression(input);
								}
							}
						}else{
							MessageDialog.openError(composite.getShell(), "错误",
									"服务【" + service.getDisplayName()
											+ "】的接口不能为null");
						}
					}else{
						MessageDialog.openError(composite.getShell(), "错误",
								"请选择要绑定的服务");
					}
				}
			});
			
			Button deleteParamAssignButton = formToolkit.createButton(parameterButtonPanel, "-", SWT.PUSH);
			deleteParamAssignButton.setToolTipText("删除输入参数绑定");
			deleteParamAssignButton.addSelectionListener(new SelectionAdapter(){
				public void widgetSelected(SelectionEvent e) {
					StructuredSelection selection = (StructuredSelection)parameterAssignmentTableViewer.getSelection();
					Iterator it = selection.iterator();
					while (it.hasNext()){
						removeInputAssignmentExpression((Assignment) it.next());
					}
				}
			});
		}
		
		Label label2 = getWidgetFactory().createLabel(composite,"返回值绑定：");

		returnBindingExpression = formToolkit.createText(composite, "");
		returnBindingExpression.setEditable(false);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		returnBindingExpression.setLayoutData(gridData);
		returnBindingExpression.setBackground(ColorConstants.white);
		
		editReturnBindingExpressionButton = formToolkit.createButton(composite, "...", SWT.PUSH);
		editReturnBindingExpressionButton.addSelectionListener(new SelectionAdapter(){

			public void widgetSelected(SelectionEvent e) {
				XPathExpressionEditDialog dialog = new XPathExpressionEditDialog(composite.getShell(),subProcessWrapper,false);
				List<Assignment> outputAssignmentList = serviceBinding==null?null:serviceBinding.getOutputAssignments();
				Expression oldExp = null;
				Expression newExp = null;
				if (outputAssignmentList!=null && outputAssignmentList.size()>0){
					Assignment assignment = outputAssignmentList.get(0);
					oldExp = assignment.getTo();
					dialog.setExpression(oldExp);
				}
				int returnCode = dialog.open();
				if (returnCode==Dialog.OK){
					newExp = dialog.getExpression();

					if (outputAssignmentList!=null && outputAssignmentList.size()>0){
						Assignment assignment = outputAssignmentList.get(0);
						assignment.setTo(newExp);
						//发布事件，更新脏标志
						if (activityWrapper!=null){
							activityWrapper.firePropertyChange("toexpression_of_output_assignment", oldExp, newExp);
						}
						//刷新
						refresh();
					}
				}
			}
		});
		
		
		return composite;
	}
	
	protected void firePropertyModifyEvent(boolean propertyIsOK,String errorMessage,String propertyName,Object newValue,Object oldValue) {
		for (IPropertyValidateListener listener : listeners){
			listener.onValidateResult(propertyIsOK,errorMessage,propertyName,newValue,oldValue);
		}
	}

	public void refresh() {		
		if (service != null) {
			String dispName = service.getDisplayName();
			if (dispName != null && !dispName.trim().equals("")) {
				serviceNameText.setText(dispName);
			} else {
				serviceNameText.setText(service.getName());
			}

		}else{
			serviceNameText.setText("");
			
		}
		
		String operationName = serviceBinding==null?"":serviceBinding.getOperationName();
		List<Assignment> inputAssignmentList = serviceBinding==null?null:serviceBinding.getInputAssignments();
		List<Assignment> outputAssignmentList = serviceBinding==null?null:serviceBinding.getOutputAssignments();
		StringBuffer sbuf = new StringBuffer();
		if (operationName!=null && !operationName.trim().equals("")){
			if (service!=null && service instanceof HumanService){
				methodNameText.setText(operationName);
			}else{
				sbuf.append(operationName).append("(");
				if (inputAssignmentList!=null){
					for (int i=0;i<inputAssignmentList.size();i++){
						Assignment assginment = inputAssignmentList.get(i);
						Expression toExp = assginment.getTo();
						QName dataType = toExp.getDataType();
						if (dataType!=null){
							sbuf.append(dataType.getLocalPart()).append(" ");
						}
						
						sbuf.append(toExp.getName());
						if (i<inputAssignmentList.size()-1){
							sbuf.append(",");
						}
					}
				}
				sbuf.append(")").append(": ");
				if (outputAssignmentList!=null && outputAssignmentList.size()>0){
					Assignment assignment = outputAssignmentList.get(0);
					Expression fromExp = assignment.getFrom();
					if (fromExp!=null && fromExp.getDataType()!=null){
						sbuf.append(fromExp.getDataType().getLocalPart());
					}
				}else{
					sbuf.append("void");
				}
				methodNameText.setText(sbuf.toString());
			}

		}else{
			methodNameText.setText("");
		}

		
		//更新输入参数列表
		parameterAssignmentTableViewer.setInput(serviceBinding);
		
		//更新输出参数
		if (outputAssignmentList!=null && outputAssignmentList.size()>0){
			Assignment assignment = outputAssignmentList.get(0);
			Expression toExp = assignment.getTo();
			returnBindingExpression.setText(toExp.getDisplayName());
			editReturnBindingExpressionButton.setEnabled(true);
			
			
		}else{
			returnBindingExpression.setText("无返回值");
			editReturnBindingExpressionButton.setEnabled(false);
		}
		
		validateBinding();


    	parameterAssignmentTableViewer.refresh();
    	Table table = parameterAssignmentTableViewer.getTable();
    	for( int i = 0; i < table.getColumnCount(); i++ )
    	    table.getColumn(i).pack();

	}
	
	protected void validateBinding(){
		if (service==null){
			firePropertyModifyEvent(false,"请选择需要绑定的Service","SERVICE",null,null);
			return;
		}
		String operationName = serviceBinding==null?"":serviceBinding.getOperationName();
		if (operationName==null || operationName.trim().equals("")){
			firePropertyModifyEvent(false,"请选择Service的一个操作。","OPERATION",null,null);
			return;
		}
		//canSelectServiceAndMethod表名该编辑表单是在property页面中，需要检查合法性
		//如果在wizard中不需要检查该合法性。
		if (canSelectServiceAndMethod){//
			List<Assignment> inputAssignmentList = serviceBinding==null?null:serviceBinding.getInputAssignments();
			for (Assignment assignment : inputAssignmentList){
				Expression exp = assignment.getFrom();
				if (Expression.EXPRESSION_DISPLAY_NAME_TIP.equals(exp.getDisplayName())){
					firePropertyModifyEvent(false,"请完善赋值表达式","EXPRESSION",null,null);
					return;
				}
				exp = assignment.getTo();
				if (Expression.EXPRESSION_DISPLAY_NAME_TIP.equals(exp.getDisplayName())){
					firePropertyModifyEvent(false,"请完善赋值表达式","EXPRESSION",null,null);
					return;
				}
			}
			
			List<Assignment> outputAssignmentList = serviceBinding==null?null:serviceBinding.getOutputAssignments();

			if (outputAssignmentList!=null && outputAssignmentList.size()>0){
				Assignment assignment = outputAssignmentList.get(0);
				Expression exp = assignment.getFrom();
				if (Expression.EXPRESSION_DISPLAY_NAME_TIP.equals(exp.getDisplayName())){
					firePropertyModifyEvent(false,"请完善赋值表达式","EXPRESSION",null,null);
					return;
				}
				exp = assignment.getTo();
				if (Expression.EXPRESSION_DISPLAY_NAME_TIP.equals(exp.getDisplayName())){
					firePropertyModifyEvent(false,"请完善赋值表达式","EXPRESSION",null,null);
					return;
				}
			}
		}
		firePropertyModifyEvent(true,null,"STRUCTURE","1","0");//所有的参数合法
	}
	
	protected FormToolkit getWidgetFactory(){
		if (formToolkit==null){
			formToolkit = new FormToolkit(Display.getCurrent());
		}

		return formToolkit;
	}
	
	class MyTableContentProvider extends ArrayContentProvider{
	    public Object[] getElements(final Object inputElement) {
	        if (inputElement instanceof ServiceBinding) {
	        	return ((ServiceBinding)inputElement).getInputAssignments().toArray();
			}
	        return new Object[0];
	    }
	}
	
	class MyCellEditor extends DialogCellEditor{
		
		public MyCellEditor(Composite parent){
			super(parent);
		}
		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.DialogCellEditor#openDialogBox(org.eclipse.swt.widgets.Control)
		 */
		@Override
		protected Object openDialogBox(Control cellEditorWindow) {
			Expression oldFromExpression = (Expression)this.getValue();
			ExpressionImpl tmp = new ExpressionImpl();
			tmp.setBody(oldFromExpression.getBody());
			tmp.setDataType(oldFromExpression.getDataType());
			tmp.setDisplayName(oldFromExpression.getDisplayName());
			tmp.setLanguage(oldFromExpression.getLanguage());
			tmp.setName(oldFromExpression.getName());
			
			
			XPathExpressionEditDialog dialog = new XPathExpressionEditDialog(cellEditorWindow.getShell(),
					subProcessWrapper,true);
			dialog.setExpression(tmp);
			int returnCode = dialog.open();
			if (returnCode==Dialog.OK){
				return dialog.getExpression();
			}
			return null;
		}
	    protected void updateContents(Object value) {
	        if (getDefaultLabel() == null) {
				return;
			}

	        String text = "";//$NON-NLS-1$
	        if (value != null) {
	        	Expression fromExpression = (Expression)value;
	        	if (fromExpression.getBody()!=null && !fromExpression.getBody().trim().equals("")){
	        		text = fromExpression.getBody();
	        	}else{
	        		text = fromExpression.getDisplayName();
	        	}
			}
	        getDefaultLabel() .setText(text);
	    }
	}

	class MyTableLabelProvider
	   extends LabelProvider
	   implements ITableLabelProvider {
	   public Image getColumnImage(
	      Object element, int index) {
	       return null;
	   }
	   public String getColumnText(Object element, int index) {
	      Assignment assignment = (Assignment) element;
	      Expression toExp = assignment.getTo();
	      Expression fromExp = assignment.getFrom();
	      switch (index) {
	         case 0 :
	            return toExp.getDisplayName();
	         case 1 :
	        	return toExp.getDataType().getLocalPart();
	         case 2 :
	        	 if (fromExp.getBody()!=null && !fromExp.getBody().trim().equals("")){
	        		 return fromExp.getBody();
	        	 }else{
	        		 return fromExp.getDisplayName();
	        	 }
	         
	         default :
	            return "unknown " + index;
	      }
	   }
	}
	
	class OperationSelectionDialog extends TrayDialog{
		private ServiceDef serviceDef = null;
		private TableViewer operationListTableViewer = null;
		private OperationDef operation = null;
		
		public OperationDef getSelectedOperation(){
			return operation;
		}
		protected void okPressed() {
			if (operationListTableViewer!=null){
				ISelection selection = operationListTableViewer.getSelection();
				if (selection!=null){
					Object obj = ((StructuredSelection)selection).getFirstElement();
					operation = (OperationDef)obj;

				}
			}

			super.okPressed();
		}
		public OperationSelectionDialog(Shell shell,ServiceDef service){
			super(shell);
			serviceDef = service;
		}
		protected void configureShell(Shell newShell) {
			super.configureShell(newShell);
			newShell.setText("选择待绑定的操作");
		}
		
		protected Control createDialogArea(Composite parent) {
			Composite container = (Composite) super.createDialogArea(parent);
			container.setLayout(new GridLayout(1, false));
			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			FormToolkit formToolkit = new FormToolkit(Display.getCurrent());

			operationListTableViewer = new TableViewer(container, SWT.SINGLE | SWT.BORDER
					| SWT.V_SCROLL| SWT.FULL_SELECTION);
			Table table = operationListTableViewer.getTable();
			table.setHeaderVisible(true);
			table.setLinesVisible(true);
			table.setLayoutData(gridData);
			

			String[] columnNames = new String[] { "操作名称","输入参数","输出参数" };
			int[] columnAlignments = new int[] { SWT.LEFT,SWT.LEFT, SWT.LEFT,SWT.LEFT};
			for (int i = 0; i < columnNames.length; i++) {
				TableViewerColumn tableColumn = new TableViewerColumn(operationListTableViewer,
						columnAlignments[i]);
				tableColumn.getColumn().setText(columnNames[i]);
				tableColumn.getColumn().setResizable(true);
				tableColumn.getColumn().setMoveable(true);
//				tableColumnLayout.setColumnData(tableColumn, new ColumnWeightData(1, ColumnWeightData.MINIMUM_WIDTH, true));
			}
			
			operationListTableViewer.setContentProvider(new ArrayContentProvider());
			operationListTableViewer.setLabelProvider(new OperationListTableLabelProvider());
			
			operationListTableViewer.addDoubleClickListener(new IDoubleClickListener(){

				public void doubleClick(DoubleClickEvent event) {
					ISelection selection = event.getSelection();
					if (selection!=null && selection instanceof StructuredSelection){
						Object obj = ((StructuredSelection)selection).getFirstElement();
						if (obj!=null){
							okPressed();
						}
					}				
				}
				
			});
			InterfaceDef _interface = serviceDef.getInterface();
			if (_interface!=null){
				operationListTableViewer.setInput(_interface.getOperations());

			}
	    	for( int i = 0; i < table.getColumnCount(); i++ )
	    	    table.getColumn(i).pack();

			return container;
		}
		
		class OperationListTableLabelProvider extends LabelProvider
		   implements ITableLabelProvider{

			/* (non-Javadoc)
			 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
			 */
			public Image getColumnImage(Object element, int columnIndex) {
				// TODO Auto-generated method stub
				return null;
			}

			/* (non-Javadoc)
			 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
			 */
			public String getColumnText(Object element, int columnIndex) {
				OperationDef operation = (OperationDef)element;
				switch (columnIndex ){
				case 0:
					return operation.getOperationName();
				case 1:
					List<Input> inputs = operation.getInputs();
					StringBuffer sbuf = new StringBuffer("");
					if (inputs!=null && inputs.size()>0){
						sbuf.append("(");
						for (int i=0;i<inputs.size();i++){
							Input input = inputs.get(i);
							sbuf.append(input.getDataType().getLocalPart())
								.append(" ")
								.append(input.getName());
							if (i<inputs.size()-1){
								sbuf.append(",");
							}
						}
						sbuf.append(")");
					}
					return sbuf.toString();
				case 2:
					List<Output> outputs = operation.getOutputs();
					StringBuffer sbuf2 = new StringBuffer("");
					if (outputs!=null && outputs.size()>0){
						for (int i=0;i<outputs.size();i++){
							Output input = outputs.get(i);
							sbuf2.append(input.getDataType().getLocalPart())
								.append(" ")
								.append(input.getName());
							if (i<outputs.size()-1){
								sbuf2.append(",");
							}
						}
					}
					return sbuf2.toString();
				}
					
				return null;
			}
			
		}
	}
	class ServiceSelectionDialog extends TrayDialog{
		WorkflowProcess workflowProcess = null;
		TableViewer serviceListTableViewer = null;
		ServiceDef selectedService = null;
		
		public ServiceSelectionDialog(Shell shell,WorkflowProcess process){
			super(shell);
			workflowProcess = process;
		}
		protected void configureShell(Shell newShell) {
			super.configureShell(newShell);
			newShell.setText("选择待绑定的服务");
		}
		
		protected void okPressed() {
			if (serviceListTableViewer!=null){
				ISelection selection = serviceListTableViewer.getSelection();
				if (selection!=null){
					Object obj = ((StructuredSelection)selection).getFirstElement();
					selectedService = (ServiceDef)obj;

				}
			}

			super.okPressed();
		}
		
		public ServiceDef getSelectedService(){
			return this.selectedService;
		}
				
		protected Control createDialogArea(Composite parent) {
			Composite container = (Composite) super.createDialogArea(parent);
			container.setLayout(new GridLayout(1, false));
			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			FormToolkit formToolkit = new FormToolkit(Display.getCurrent());

			serviceListTableViewer = new TableViewer(container, SWT.SINGLE | SWT.BORDER
					| SWT.V_SCROLL| SWT.FULL_SELECTION);
			Table table = serviceListTableViewer.getTable();
			table.setHeaderVisible(true);
			table.setLinesVisible(true);
			table.setLayoutData(gridData);
			

			String[] columnNames = new String[] { "服务名称","中文名","描述信息" };
			int[] columnAlignments = new int[] { SWT.LEFT,SWT.LEFT, SWT.LEFT,SWT.LEFT};
			for (int i = 0; i < columnNames.length; i++) {
				TableViewerColumn tableColumn = new TableViewerColumn(serviceListTableViewer,
						columnAlignments[i]);
				tableColumn.getColumn().setText(columnNames[i]);
				tableColumn.getColumn().setResizable(true);
				tableColumn.getColumn().setMoveable(true);
//				tableColumnLayout.setColumnData(tableColumn, new ColumnWeightData(1, ColumnWeightData.MINIMUM_WIDTH, true));
			}
			
			serviceListTableViewer.setContentProvider(new ArrayContentProvider());
			serviceListTableViewer.setLabelProvider(new ServiceListTableLabelProvider());
			
			serviceListTableViewer.addDoubleClickListener(new IDoubleClickListener(){

				public void doubleClick(DoubleClickEvent event) {
					ISelection selection = event.getSelection();
					if (selection!=null && selection instanceof StructuredSelection){
						Object obj = ((StructuredSelection)selection).getFirstElement();
						if (obj!=null){
							okPressed();
						}
					}				
				}
				
			});
			serviceListTableViewer.setInput(workflowProcess.getServices());
	    	for( int i = 0; i < table.getColumnCount(); i++ )
	    	    table.getColumn(i).pack();
			return container;
		}
		class ServiceListTableLabelProvider extends LabelProvider
		   implements ITableLabelProvider{

			/* (non-Javadoc)
			 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
			 */
			public Image getColumnImage(Object element, int columnIndex) {
				// TODO Auto-generated method stub
				return null;
			}

			/* (non-Javadoc)
			 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
			 */
			public String getColumnText(Object element, int columnIndex) {
				ServiceDef service = (ServiceDef)element;
				switch (columnIndex ){
				case 0:
					return service.getName();
				case 1:
					return service.getDisplayName();
				case 2:
					return service.getDescription();
				}
					
				return null;
			}
			
		}
	}

	class InputSelectionDialog extends TrayDialog{
		List<Input> inputList = null;
		Input selectedInput = null;
		TableViewer formURLParameterTableViewer = null;
		public InputSelectionDialog(Shell shell,List<Input> ops){
			super(shell);
			this.inputList = ops;
		}
		protected void configureShell(Shell newShell) {
			super.configureShell(newShell);
			newShell.setText("选择待绑定的输入参数");
		}
		public Input getSelectedInput(){
			return selectedInput ;
		}
		
		protected void okPressed() {
			if (formURLParameterTableViewer!=null){
				ISelection selection = formURLParameterTableViewer.getSelection();
				if (selection!=null){
					Object obj = ((StructuredSelection)selection).getFirstElement();
					selectedInput = (Input)obj;

				}
			}

			super.okPressed();
		}
		protected Control createDialogArea(Composite parent) {
			Composite container = (Composite) super.createDialogArea(parent);
			container.setLayout(new GridLayout(1, false));
			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			
			formURLParameterTableViewer = new TableViewer(container, SWT.MULTI
					| SWT.BORDER | SWT.V_SCROLL | SWT.FULL_SELECTION);
			Table table = formURLParameterTableViewer.getTable();
			table.setHeaderVisible(true);
			table.setLinesVisible(true);
			gridData = new GridData(GridData.FILL_BOTH);
			gridData.horizontalSpan = 1;
			gridData.grabExcessVerticalSpace = true;
			gridData.heightHint = 80;
			table.setLayoutData(gridData);

			final String[] columnNames = new String[] { "参数名称", "中文名", "类型" };
			int[] columnAlignments = new int[] { SWT.LEFT, SWT.LEFT, SWT.LEFT };
			for (int i = 0; i < columnNames.length; i++) {
				TableColumn tableColumn = new TableColumn(table,
						columnAlignments[i]);
				tableColumn.setText(columnNames[i]);
				if (i == 0)
					tableColumn.setWidth(100);
				if (i == 1)
					tableColumn.setWidth(100);
				if (i == 2)
					tableColumn.setWidth(200);
			}
			
			formURLParameterTableViewer
			.setContentProvider(new ArrayContentProvider());
			formURLParameterTableViewer
			.setLabelProvider(new InputListTableLabelProvider());
			
			formURLParameterTableViewer.addDoubleClickListener(new IDoubleClickListener(){

				public void doubleClick(DoubleClickEvent event) {
					okPressed();
					
				}
				
			});

			formURLParameterTableViewer.setInput(inputList);
			return container;
		}
		
		class InputListTableLabelProvider extends LabelProvider
		   implements ITableLabelProvider {

			/* (non-Javadoc)
			 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
			 */
			public Image getColumnImage(Object element, int columnIndex) {
				// TODO Auto-generated method stub
				return null;
			}

			/* (non-Javadoc)
			 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
			 */
			public String getColumnText(Object element, int columnIndex) {
				Input input = (Input) element;

				switch (columnIndex) {
				case 0:
					return input.getName();
				case 1:
					return input.getDisplayName();
				case 2:
					QName dataType = input.getDataType();

					return (dataType == null ? "" : dataType.getPrefix() + ":"
							+ dataType.getLocalPart());

				default:
					return "unknown " + columnIndex;
				}
			}
			
		}
	}
}
